﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
//Author: salty
//Date: 2019.06.15
//行动力模块 设计为单例以供其他模块方便调用（行动力涉及多个模块，持有引用会较为复杂）
//目前影响行动力的操作：挖掘（MouseController） Player行走 建塔
//由于模块较小可能会暂时决定UI数值显示不作分离
public class APController : MonoBehaviour
{
    public static APController Instance
    {
        get
        {
            if (_Instance == null)
            {
                _Instance = FindObjectOfType<APController>();
            }
            if (!_Instance)
            {
                GameObject obj = new GameObject("APController");
                _Instance = obj.AddComponent<APController>();
            }
            return _Instance;
        }
    }
    private static APController _Instance;

    //显示行动值的UI
    [SerializeField]
    public Text uiText;
    public Image APImage;
    
    #region 批次设置
    [System.Serializable]
    public class WaveUnit
    {
        //出兵类型，后续阶段改成枚举
        public int soldierIndex;
        //连续出几只
        public int unitRepeatTimes;
        //在基础秒数后延迟n秒再出一只 默认不修改为0
        public float unitDelaySecond;
    }

    [System.Serializable]
    public class WaveTemplate
    {
        public string templateName;
        public List<WaveUnit> waveUnits = new List<WaveUnit>();
        //public float waveDelaySecond;
    }

    [System.Serializable]
    public class Wave
    {
        public string templateName;
        public int waveRepeatTimes;
    }

    private Dictionary<string, WaveTemplate> WaveTemplateDict = new Dictionary<string, WaveTemplate>();

    //一个WaveUnit生成几个兵， 一个List<WaveUnit>代表一批
    [SerializeField]
    public List<WaveTemplate> waveTempletes = new List<WaveTemplate>();

    //利用从Template中读取批次信息，按顺序处理生成批数
    [SerializeField]
    public List<Wave> waves = new List<Wave>();

    [SerializeField]
    public float basicDelayBetweenUnit = 1.0f;
    #endregion
    
    #region 各种初始值
    //由于人物可以走半格，因此目前记录人物行走时间来计算行动力（满该时间则扣一点行动力）
    public float playerWalkTimePerAP = 0.5f;
    //public int APToBreakBlock = 1;
    private float timeHasWalked = 0;
    //AP阈值（可能和初始值不一样 而且可以充值改变？）
    public float threshold = 10;
    public float waitsec = 1.0f;

    //每波敌人来之前增加的金钱
    public float moneyPerWave = 10f;

    #endregion

    private float AP
    {
        set
        {
            _ap = value;
            RefreshUI();
        }
        get
        {
            return _ap;
        }
    }
    private float _ap;

    public int wave = 0;
    private int number = 5;

    private void Start()
    {
        if (ConstOfMap.loadgame)
        {
            wave = ConstOfMap.save.wave;
            threshold = (int)(wave / 5) * 10 + 30;
            AP = ConstOfMap.save.AP;
            number = (int)(wave / 2) + 5;
        }
        else
        {
            AP = threshold;
            wave = 0;
        }
        /*
        for (int i = 0; i < waveTempletes.Count; ++i)
        {
            WaveTemplateDict[waveTempletes[i].templateName] = waveTempletes[i];
        }
        */
        //StartCoroutine(CheckAPExhaustedCoroutine());
    }

    private void Update()
    {
        while (AP <= 0)
        {
            wave += 1;
            if (wave % 5 == 0)
                threshold += 10;
            AP = threshold + AP;
            if (wave % 5 == 0)
                number += 1;
            Player.Instance.Heal();
            ResourceManager.Instance.GainResource(ResourceType.Money, moneyPerWave);
            StartCoroutine(WaveCreateCoroutine(number));
        }
    }

    public float GetAP()
    {
        return AP;
    }

    //增加无需返回成功或失败，若已满则也不会告诉调用方
    public void AddAP(int value)
    {
        if(AP + value > threshold)
        {
            AP = threshold;
        }
        else
        {
            AP += value;
        }
    }

    public bool TryCostAp(float cost)
    {
        if (AP <= 0)
            return false;
        return true;
    }

    public void CostAp(float cost)
    {
        AP -= cost;
    }

    //如果返回true则已正确减少AP，返回false则AP不足，拒绝操作
    public bool TryDecreaseAPForBuilding(BuildingType type)
    {
        int value = BuildingManager.Instance.GetRequiredAP(type);
        if (AP <= 0)
            return false;
        AP -= value;
        return true;
    }

    public bool CheckDecreaseAPForBuilding(BuildingType type)
    {
        if (AP <= 0)
            return false;
        return true;
    }

    public bool TryDecreaseAPForBreakBlock(int cost)
    {
        if (AP <= 0)
            return false;
        AP -= cost;
        return true;
    }

    public bool TryDecreaseAPForBreakBlock(float cost)
    {
        if (AP <= 0)
            return false;
        AP -= cost;
        return true;
    }

    public bool CheckDecreaseAPForRepair(BuildingType type)
    {
        if (AP <= 0)
            return false;
        return true;
    }

    public bool TryDecreaseAPForRepair(BuildingType type)
    {
        int value = BuildingManager.Instance.GetRequiredAP(type);
        if (AP <= 0)
            return false;
        AP -= value / 2;
        return true;
    }

    public bool CheckDecreaseAPForBreakBlock(int cost)
    {
        if (AP <= 0)
            return false;
        return true;
    }

    public bool CheckDecreaseAPForBreakBlock(float cost)
    {
        if (AP <= 0)
            return false;
        return true;
    }

    public bool TryDecreaseAPForWalk()
    {
        if(AP <= 0)
        {
            //没AP，别走了，记账清零
            return false;
        }
        AP -= Time.deltaTime * 2 * playerWalkTimePerAP;
        return true;
    }

    void RefreshUI()
    {
        uiText.text = System.Math.Floor(AP).ToString() + "/" + System.Math.Round(threshold).ToString();
        APImage.fillAmount= ((float)System.Math.Floor(AP)/ (float)System.Math.Round(threshold))*0.75f;
    }

    /*
    IEnumerator CheckAPExhaustedCoroutine()
    {
        for (int i = 0; i < waves.Count; ++i)
        {
            //循环波数
            for (int r = 0; r < waves[i].waveRepeatTimes; ++r)
            {
                StartCoroutine(WaveCreateCoroutine(i));
                while (AP > 0)
                {
                    yield return null;
                }
                AP = threshold + AP;
            }
        }
    }
    */

    IEnumerator WaveCreateCoroutine(int i)
    {
        /*
        if(!WaveTemplateDict.ContainsKey(waves[i].templateName))
        {
            Debug.LogError("无该兵批模板！");
            yield break;
        }
        */
        //WaveTemplate wt = WaveTemplateDict[waves[i].templateName];
        MessageController.Instance.SendMsg("敌军来袭!");
        for (int u = 0; u < number; ++u)
        {
            SoldierManager.Instance.CreateSoldier(Genetic.Instance.GenerateSoldier());
            yield return new WaitForSeconds(waitsec);

            /*
            WaveUnit currUnit = wt.waveUnits[u];
            for (int r = 0; r < currUnit.unitRepeatTimes; ++r)
            {
                //Debug.Log(basicDelayBetweenUnit + currUnit.unitDelaySecond);
                yield return new WaitForSeconds(basicDelayBetweenUnit + currUnit.unitDelaySecond);
                SoldierManager.Instance.CreateSoldier(currUnit.soldierIndex);
            }
            */
        }
    }
}
